﻿#include "OiPCH.hpp"
//#include "PLScannerCore/Camera/Optex/UrlDownloadFile.hpp"

#include <QtConcurrent/QtConcurrentRun>
#include <QLocalServer>
#include <QLocalSocket>
#include <QSharedMemory>
#include <QElapsedTimer>
#include <qt_windows.h>
#include <wlanapi.h>
#include <atlbase.h>
#include <mbnapi.h>
#include <deque>

#include "RibbonControls/RcOfficePopupWindow.hpp"
#include "RibbonControls/RcRibbonPage.hpp"
#include "RibbonControls/RcRibbonGroup.hpp"


#pragma comment(lib, "mbnapi_uuid.lib")

using namespace Oi::PLScannerCore;

namespace Oi { namespace PLScannerDll {

class PLScannerWindowImpl : public Impl<PLScannerWindow>
{
public:
    void init();
    void exit();

public:
    void start();

public:
    QAction* createAction(const QIcon& icon, const QString &text, const char* member = nullptr);

public:
    bool callPasswordInput(const QString typeStr, QString& passkeys);

public:
    void setParams(const ProductParams& params);

public:
    void relocateOutput();

public:
    void updateTitle();

public:
    void updateFormular();

public:
    void setTitleStatus(int);

public:
    void onUserUpdate();

public:
    MessageOutput* _progOutput = nullptr;
    SensorAcquire* _acquire = nullptr;
    PLScannerWorker* _work = nullptr;

    QDockWidget* _progOutputDocket;

    Oi::RibbonBar* _ribbonBar;

    QAction* _openAction;
    QAction* _startAction;
    QAction* _saveAction;
    QAction* _formulaAction;
    QAction* _importAction;

    QAction* _settingAction;
    QAction* _userManage;
    QAction* _superAction;
  
    QMenu* _calibMenu;
    QAction* _calibrateAction;
    QAction* _calibrate2Action;
    QAction* _verificationAction;
    QAction* _zeroAction;

    QLabel*  _formulaName;
    QLabel*  _nextFormulaName;
    QLabel* _titleStatus;

public:
    QLabel* _statusLabel;
    QToolButton* _userLabel;
    QProgressBar* _progress;

public:
    ProductParams _params;

public:
    QStackedWidget * _pages;
    PageAbstract* _page0;
    PageAbstract* _page1;
    ValuePage* _page2;
    PageAbstract* _page3;
    PageAbstract* _page4;

    QPushButton* _pRealtimeTitleBtn;
    QPushButton* _pConcludeTitleBtn;
    QPushButton* _pPointMeasureTitleBtn;
    QPushButton* _pRecordTitleBtn;
    QPushButton* _pRecord1TitleBtn;

    QPushButton* _pStartTitleBtn;
    QPushButton* _pFormularTitleBtn;
    QPushButton* _pExitTitleBtn;

    QButtonGroup* _buttonGroup;
    QMap<int, QPushButton*> _pageBtns;

    ProductMeasurePage _pageFlag;
    int _interfaceError;

public:
    QFuture<void> _future;
};

void PLScannerWindowImpl::init()
{
    OI_Q(PLScannerWindow);

    PLScanner::instance()->init();
    QString strname = PLScanner::instance()->themeName;
    if(QResource::registerResource(QString("themes/%1.rcc").arg(PLScanner::instance()->themeName)))
    {
        qApp->style()->setProperty("theme", PLScanner::instance()->themeName);
    }

    OI_ASSERT(!qApp->property("mainWindow").isValid());

    QSettings* settings = Core::OiSettings()->object();

#pragma region actions
    _startAction = createAction(QIcon(":/resources/images/ExecuteAll.png"), PLScannerWindow::tr("开始"), SLOT(onStart()));
    _startAction->setToolTip(PLScannerWindow::tr("开始运行"));
    _startAction->setCheckable(true);

    _openAction = createAction(QIcon(":/resources/images/FileOpen.png"), PLScannerWindow::tr("打开数据"), SLOT(onOpen()));
    _openAction->setToolTip(PLScannerWindow::tr("打开数据"));

    _saveAction = createAction(QIcon(":/"+PLScanner::instance()->resourceName+"/save.png"), PLScannerWindow::tr("保存"), SLOT(onSave()));
    _saveAction->setToolTip(PLScannerWindow::tr("保存当前数据"));


//     _modeAction = createAction(QIcon(":/" + PLScanner::instance()->resourceName + "/pointMeasure.png"), PLScannerWindow::tr("定点测量"), SLOT(onFixedMeasure()));
//     _modeAction->setToolTip(PLScannerWindow::tr("打开定点测量"));

    _formulaAction = createAction(QIcon(":/resources/images/Verbose.png"), PLScannerWindow::tr("配方"), SLOT(onProduct()));
    _formulaAction->setToolTip(PLScannerWindow::tr("选择配方"));

//     _recordViewAction = createAction(QIcon(":/resources/images/Verbose.png"), PLScannerWindow::tr("记录"), SLOT(onRecord()));
//     _recordViewAction->setToolTip(PLScannerWindow::tr("打开记录"));

    _calibrateAction = createAction(QIcon(":/"+PLScanner::instance()->resourceName+"/calibration.png"), PLScannerWindow::tr("标定"), SLOT(onCalibration()));
    _calibrate2Action = createAction(QIcon(":/" + PLScanner::instance()->resourceName + "/calibration.png"), PLScannerWindow::tr("连续标定"), SLOT(onCalibration2()));
    _verificationAction = createAction(QIcon(":/" + PLScanner::instance()->resourceName + "/verification.png"), PLScannerWindow::tr("精度验证"), SLOT(onVerification()));
    _settingAction = createAction(QIcon(":/"+PLScanner::instance()->resourceName+"/setting.png"), PLScannerWindow::tr("软件设置"), SLOT(onSettings()));

#pragma endregion

    auto actionBar = new Oi::RibbonQuickActionBar(q);

    actionBar->addAction(_startAction);
    actionBar->addAction(_saveAction);
//    actionBar->addAction(_modeAction);
    actionBar->addAction(_formulaAction);
//    actionBar->addAction(_recordViewAction);

    QMenu* fileMenu = actionBar->addMenu(PLScannerWindow::tr("文件"));
    QMenu* settingsMenu = actionBar->addMenu(PLScannerWindow::tr("设置"));
    QMenu* toolMenu = actionBar->addMenu(PLScannerWindow::tr("工具"));
    QMenu* langMenu = actionBar->addMenu(PLScannerWindow::tr("语言"));
    QMenu* helpMenu = actionBar->addMenu(PLScannerWindow::tr("帮助"));

    _ribbonBar = q->ribbonBar();

    _ribbonBar->attachQuickActionBar(actionBar);

    _ribbonBar->setFrameThemeEnabled(true);

    QLibrary("OiOperators.dll").load();

    QStringList packages;

    for (const QFileInfo& entry : QDir("packages").entryInfoList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot))
    {
        if (QFile::exists(entry.absoluteFilePath() + "\\" + entry.fileName() + ".dll"))
        {
            packages << entry.absoluteFilePath();
        }
    }

    if (!packages.empty())
    {
        qputenv("PATH", (QProcessEnvironment::systemEnvironment().value("PATH") + ";" + packages.join(";")).toLocal8Bit());
    }

    void* routine = nullptr;

    for (const QFileInfo& entry : QDir("packages").entryInfoList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot))
    {
        if (QFile::exists(entry.absoluteFilePath() + "\\" + entry.fileName() + ".dll"))
        {
            if ((routine = QLibrary::resolve(entry.absoluteFilePath() + "\\" + entry.fileName() + ".dll", "OiPackageInit")) != NULL)
            {
                reinterpret_cast<void(*)(void)>(routine)();
            }
        }
    }

    qApp->setProperty("mainWindow", QVariant::fromValue<QWidget*>(q));

#pragma region toolbar

    #pragma region fileMenu
    fileMenu->addAction(_startAction);
    fileMenu->addAction(_openAction);
    fileMenu->addAction(_saveAction);
    fileMenu->addSeparator();
    fileMenu->addAction(_formulaAction);
    _importAction = fileMenu->addAction(PLScannerWindow::tr("导入配方"));
    fileMenu->addSeparator();
    fileMenu->addAction(PLScannerWindow::tr("退出"), q, SLOT(onClose()));

    q->connect(_importAction, &QAction::triggered, q, &PLScannerWindow::onImport);
    #pragma endregion

    #pragma region settingsMenu

    settingsMenu->addAction(_settingAction);
    settingsMenu->addSeparator();

    _userManage = settingsMenu->addAction(PLScannerWindow::tr("用户管理"));
    settingsMenu->addSeparator();

    (_superAction = settingsMenu->addAction(PLScannerWindow::tr("超级权限")))->setCheckable(true);

    q->connect(_userManage, &QAction::triggered, q, &PLScannerWindow::onUser);
    q->connect(_superAction, &QAction::triggered, q, &PLScannerWindow::onSuper);
    #pragma endregion

    #pragma region toolMenu
    _calibMenu = toolMenu->addMenu(PLScannerWindow::tr("标定"));
    _calibMenu->addAction(_calibrateAction);
    _calibMenu->addAction(_calibrate2Action);
    _zeroAction = toolMenu->addAction(PLScannerWindow::tr("零点校准"));
    q->connect(_zeroAction, &QAction::triggered, q, &PLScannerWindow::onZero);

    //toolMenu->addAction(_calibrateAction);

    //toolMenu->addAction(_verificationAction);
    #pragma endregion

    #pragma region langMenu
    QString locale = settings->value("locale").toString();
    QActionGroup* languages = new QActionGroup(q);
    QAction* defaultLanguage = langMenu->addAction(PLScannerWindow::tr("系统默认"), q, SLOT(onLanguage()));
    defaultLanguage->setCheckable(true);
    defaultLanguage->setData(-1);
    languages->addAction(defaultLanguage);

    QStringList languageList;
    languageList << QLocale(QLocale::English, QLocale::UnitedStates).name()
        << QLocale(QLocale::Chinese, QLocale::China).name();

    foreach(const QString& language, languageList)
    {
        QAction* availableLangauge = langMenu->addAction(language, q, SLOT(onLanguage()));
        availableLangauge->setCheckable(true);
        availableLangauge->setData(0);
        languages->addAction(availableLangauge);
    }

    if(locale.isEmpty())
    {
        defaultLanguage->setChecked(true);
    }
    else
    {
        foreach(QAction* node, languages->actions())
        {
            if(node->text() == locale)
            {
                node->setChecked(true); break;
            }
        }
    }
    #pragma endregion

    #pragma region helpMenu
    helpMenu->addAction(PLScannerWindow::tr("帮助"), q, SLOT(onHelp()));
    helpMenu->addAction(PLScannerWindow::tr("关于"), q, SLOT(onAbout()));
    #pragma endregion

#pragma endregion

#pragma region statusbar
    _statusLabel = new QLabel();
    q->statusBar()->addWidget(_statusLabel);

    _progress = new QProgressBar();
    _progress->setRange(0, 100);
    _progress->setMinimumWidth(200);
    _progress->setMaximumWidth(200);
    q->statusBar()->addPermanentWidget(_progress);

    _userLabel = new QToolButton();
    _userLabel->setText(PLScannerWindow::tr("未登录"));
    q->statusBar()->addPermanentWidget(_userLabel);

    _progOutput = new MessageOutput(q);
    _progOutputDocket = new Ctrl::Docket(PLScannerWindow::tr("程序输出"), q);
    _progOutputDocket->setWidget(_progOutput);
    _progOutputDocket->setWindowFlags(Qt::Popup);
    _progOutputDocket->setFeatures(QDockWidget::DockWidgetClosable);
    _progOutputDocket->toggleViewAction()->setIcon(QIcon(":/resources/images/Console.png"));
    for(auto& m_button : _progOutputDocket->titleBarWidget()->findChildren<QToolButton*>())
    {
        if(m_button->toolTip() == QWidget::tr("Maximize"))
        {
            m_button->hide();
        }
    }

    q->connect(_userLabel, &QToolButton::clicked, q, &PLScannerWindow::onUser);
    q->connect(_progOutput, &MessageOutput::alarmChanged, _progOutputDocket, &QDockWidget::setVisible);
    q->connect(_progOutputDocket, &QDockWidget::visibilityChanged, q, &PLScannerWindow::onOutputVisibilityChanged);

    auto progOutputToggle = new QToolButton(q);
    progOutputToggle->setDefaultAction(_progOutputDocket->toggleViewAction());
    q->statusBar()->addPermanentWidget(progOutputToggle);
#pragma endregion

#pragma region centralWidget
    QWidget* centralWidget = new QWidget(q);
    QVBoxLayout* cLayout = new QVBoxLayout(centralWidget);
    cLayout->setContentsMargins(0, 0, 0, 0);
    cLayout->setSpacing(0);

    TitleWidget* m_title = new TitleWidget(q);
    QHBoxLayout* m_titleLayout = new QHBoxLayout(m_title);
    m_titleLayout->setContentsMargins(10, 0, 10, 0);

    QPixmap pixmap(":/"+PLScanner::instance()->resourceName+"/companyBanner.png");
    if(!pixmap.isNull())
    {
        QLabel* logo = new QLabel();
        logo->setPixmap(pixmap);
        m_titleLayout->addWidget(logo);
    }

    m_titleLayout->addStretch();

    _formulaName = new QLabel();
    _formulaName->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    _formulaName->setAlignment(Qt::AlignCenter);
    _formulaName->setFixedWidth(300);
    _formulaName->setStyleSheet("background-color: rgb(0, 255, 0);color:black");
    auto sFont = _formulaName->font();
    sFont.setPixelSize(40);
    _formulaName->setFont(sFont);

    _nextFormulaName = new QLabel();
    _nextFormulaName->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    _nextFormulaName->setAlignment(Qt::AlignCenter);
    _nextFormulaName->setFixedWidth(300);
    _nextFormulaName->setStyleSheet("background-color: gray;color:black");
    sFont.setPixelSize(40);
    _nextFormulaName->setFont(sFont);

    _titleStatus = new QLabel();
    _titleStatus->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    _titleStatus->setAlignment(Qt::AlignCenter);
    _titleStatus->setFixedSize(300, 75);
    sFont = _titleStatus->font();
    sFont.setPixelSize(40);
    _titleStatus->setFont(sFont);

    setTitleStatus(0);

    QVBoxLayout* m_formularlayout = new QVBoxLayout();
    m_formularlayout->addWidget(_formulaName);
    m_formularlayout->addWidget(_nextFormulaName);

    m_titleLayout->addLayout(m_formularlayout);
    m_titleLayout->addWidget(_titleStatus);

    cLayout->addWidget(m_title);

    _pages = new QStackedWidget(q);

    _page0 = new PlyPage(q);
    _pages->addWidget(_page0);

    _page1 = new ConcludePage(q);
    _pages->addWidget(_page1);

    _page2 = new ValuePage(q);
    _pages->addWidget(_page2);

    _page3 = new RecordPage(q);
    _pages->addWidget(_page3);

    _page4 = new FixedRecordPage(q);
    _pages->addWidget(_page4);

    _pages->setCurrentIndex(0);

    cLayout->addWidget(_pages);

    QWidget* m_pageButtonWidget = new QWidget(q);
    m_pageButtonWidget->setFixedHeight(54);
    QHBoxLayout* m_pageButtonLayout = new QHBoxLayout(m_pageButtonWidget);
    m_pageButtonLayout->setContentsMargins(10, 0, 10, 0);

    _buttonGroup = new QButtonGroup(q);
    _buttonGroup->setExclusive(true);

    _pRealtimeTitleBtn = new QPushButton();
    _pRealtimeTitleBtn->setText("(F1) " + PLScannerWindow::tr("实时"));
    _pRealtimeTitleBtn->setStyleSheet("font-size:18pt");
    _pRealtimeTitleBtn->setFixedSize(QSize(150, 40));
    _pRealtimeTitleBtn->setCheckable(true);
    _pRealtimeTitleBtn->setShortcut(Qt::Key_F1);
    _pageBtns[0] = _pRealtimeTitleBtn;
    _buttonGroup->addButton(_pRealtimeTitleBtn, 0);

    _pConcludeTitleBtn = new QPushButton();
    _pConcludeTitleBtn->setText("(F2) " + PLScannerWindow::tr("趋势"));
    _pConcludeTitleBtn->setStyleSheet("font-size:18pt");
    _pConcludeTitleBtn->setFixedSize(QSize(150, 40));
    _pConcludeTitleBtn->setCheckable(true);
    _pConcludeTitleBtn->setShortcut(Qt::Key_F2);
    _pageBtns[1] = _pConcludeTitleBtn;
    _buttonGroup->addButton(_pConcludeTitleBtn, 1);

    _pPointMeasureTitleBtn = new QPushButton();
    _pPointMeasureTitleBtn->setText("(F3) " + PLScannerWindow::tr("定点测量"));
    _pPointMeasureTitleBtn->setStyleSheet("font-size:18pt");
    _pPointMeasureTitleBtn->setFixedSize(QSize(150, 40));
    _pPointMeasureTitleBtn->setCheckable(true);
    _pPointMeasureTitleBtn->setShortcut(Qt::Key_F3);
    _pageBtns[1] = _pPointMeasureTitleBtn;
    _buttonGroup->addButton(_pPointMeasureTitleBtn, 2);

    _pRecordTitleBtn = new QPushButton();
    _pRecordTitleBtn->setText(PLScannerWindow::tr("记录(循环)"));
    _pRecordTitleBtn->setStyleSheet("font-size:18pt");
    _pRecordTitleBtn->setFixedSize(QSize(150, 40));
    _pRecordTitleBtn->setCheckable(true);
    _pageBtns[1] = _pRecordTitleBtn;
    _buttonGroup->addButton(_pRecordTitleBtn, 3);

    _pRecord1TitleBtn = new QPushButton();
    _pRecord1TitleBtn->setText(PLScannerWindow::tr("记录(定点)"));
    _pRecord1TitleBtn->setStyleSheet("font-size:18pt");
    _pRecord1TitleBtn->setFixedSize(QSize(150, 40));
    _pRecord1TitleBtn->setCheckable(true);
    _pageBtns[1] = _pRecord1TitleBtn;
    _buttonGroup->addButton(_pRecord1TitleBtn, 4);

    _pStartTitleBtn = new QPushButton();
    _pStartTitleBtn->setText("(F7) " + PLScannerWindow::tr("启动"));
    _pStartTitleBtn->setStyleSheet("font-size:18pt");
    _pStartTitleBtn->setFixedSize(QSize(150, 40));
    _pStartTitleBtn->setCheckable(false);
    _pStartTitleBtn->setShortcut(Qt::Key_F7);

    _pFormularTitleBtn = new QPushButton();
    _pFormularTitleBtn->setText("(F8) " + PLScannerWindow::tr("规格"));
    _pFormularTitleBtn->setStyleSheet("font-size:18pt");
    _pFormularTitleBtn->setFixedSize(QSize(150, 40));
    _pFormularTitleBtn->setCheckable(false);
    _pFormularTitleBtn->setShortcut(Qt::Key_F8);

    _pExitTitleBtn = new QPushButton();
    _pExitTitleBtn->setText("(Esc) " + PLScannerWindow::tr("退出"));
    _pExitTitleBtn->setStyleSheet("font-size:18pt");
    _pExitTitleBtn->setFixedSize(QSize(150, 40));
    _pExitTitleBtn->setCheckable(false);
    _pExitTitleBtn->setShortcut(Qt::Key_Escape);

    m_pageButtonLayout->addWidget(_pRealtimeTitleBtn);
    m_pageButtonLayout->addWidget(_pConcludeTitleBtn);
    m_pageButtonLayout->addWidget(_pPointMeasureTitleBtn);
    m_pageButtonLayout->addWidget(_pRecordTitleBtn);
    m_pageButtonLayout->addWidget(_pRecord1TitleBtn);
    m_pageButtonLayout->addStretch();
    m_pageButtonLayout->addWidget(_pStartTitleBtn);
    m_pageButtonLayout->addWidget(_pFormularTitleBtn);
    m_pageButtonLayout->addWidget(_pExitTitleBtn);

    _pRealtimeTitleBtn->click();

    _pageFlag = PMP_ThicknessMeasure;

    cLayout->addWidget(m_pageButtonWidget);

    q->setCentralWidget(centralWidget);

    q->centralWidget()->winId();

    q->connect(_buttonGroup, static_cast<void(QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), q, &PLScannerWindow::onButtonGroupTriggered);

    q->connect(_pStartTitleBtn, &QPushButton::clicked, q, &PLScannerWindow::onStart);

    q->connect(_pFormularTitleBtn, &QPushButton::clicked, q, &PLScannerWindow::onProduct);

    q->connect(_pExitTitleBtn, &QPushButton::clicked, q, &QWidget::close);

#pragma endregion

    _work = new PLScannerWorker(q);

    q->connect(_work, &PLScannerWorker::enterTask, q, &PLScannerWindow::onEnterTask);
    q->connect(_work, &PLScannerWorker::leaveTask, q, &PLScannerWindow::onLeaveTask);
    q->connect(_work, &PLScannerWorker::leaveRound, q, &PLScannerWindow::onResultUpdate, Qt::QueuedConnection);

    _progOutputDocket->hide();
    _nextFormulaName->hide();

    _interfaceError = 0;

    updateTitle();

    q->setWindowIcon(QIcon(":/"+PLScanner::instance()->resourceName+"/" + PLScanner::instance()->icon));

//     if (PLScanner::instance()->simulation)
//     {
//         q->showMaximized();
//     }
//     else
    {
        q->showFullScreen();
    }

    _future = QtConcurrent::run(this, &PLScannerWindowImpl::start);
}

void PLScannerWindowImpl::exit()
{
    OI_Q(PLScannerWindow);

    if(_work)
    {
        _work->stop();
    }

    if(_acquire)
    {
        _acquire->exit();
    }

    PLScanner::instance()->exit();
}

QAction* PLScannerWindowImpl::createAction(const QIcon& icon, const QString &text, const char* member)
{
    OI_Q(PLScannerWindow);

    QAction* action = new QAction(icon, text, q);

    if(member != nullptr)
    {
        q->connect(action, SIGNAL(triggered()), member);
    }

    return action;
}

void PLScannerWindowImpl::start()
{
    OI_Q(PLScannerWindow);

    if (!PLScanner::instance()->simulation)
    {
        QMetaObject::invokeMethod(q, "setProgressValue", Q_ARG(int, 5));

        Sleep(1000);
        
        QMetaObject::invokeMethod(q, "setProgressValue", Q_ARG(int, 100));

    }
    
    QMetaObject::invokeMethod(q, "onReady");
}


bool PLScannerWindowImpl::callPasswordInput(const QString typeStr, QString& passkeys)
{
    OI_Q(PLScannerWindow);
    
    QByteArray password = Core::Settings::instance()->value(typeStr).toByteArray();

    if(!password.isEmpty())
    {
        bool ok = false;

        passkeys = Ctrl::TouchInputDialog::getText(q, PLScannerWindow::tr("输入解锁密码"), PLScannerWindow::tr("密码"), Ctrl::TouchInputDialog::Secret, 1, Core::Value(), &ok, Qt::Dialog | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint).toString();

        if(!ok)
        {
            return false;
        }

        if(passkeys.startsWith('!'))
        {
            if(QCryptographicHash::hash(( Core::OiBaseCreatorName() + passkeys.mid(1) ).toLatin1(), QCryptographicHash::Md5) != password)
            {
                return false;
            }
        }
        else
        {
            if(QCryptographicHash::hash(( Core::OiBaseCreatorName() + passkeys ).toLatin1(), QCryptographicHash::Md5) != password)
            {
                return false;
            }
        }

        return true;
    }
    else
    {
        return true;
    }
}

void PLScannerWindowImpl::relocateOutput()
{
    OI_Q(PLScannerWindow);
    auto base = q->statusBar()->mapToGlobal(QPoint(0, 0));
    _progOutputDocket->setGeometry(base.x() + q->statusBar()->size().width() - 255, base.y() - 510, 250, 500);
}


void PLScannerWindowImpl::updateTitle()
{
    OI_Q(PLScannerWindow);

    if (_pageFlag == PMP_FixedMeasure)
    {
        q->setWindowTitle(PLScannerWindow::tr("%1 %2 %3 - 定点测量模式").arg(PLScanner::instance()->company)
            .arg("PLScanner")
            .arg(PLScanner::instance()->softVersion));
    }
    else if (_pageFlag == PMP_ThicknessMeasure)
    {
        q->setWindowTitle(PLScannerWindow::tr("%1 %2 %3 - 行程测量模式").arg(PLScanner::instance()->company)
            .arg("PLScanner")
            .arg(PLScanner::instance()->softVersion));
    }
}

void PLScannerWindowImpl::updateFormular()
{
    _formulaName->setText(ProductParams::current());

    if (!ProductParams::next().isEmpty())
    {
        _nextFormulaName->setText(ProductParams::next());
        _nextFormulaName->show();
    }
    else
    {
        _nextFormulaName->hide();
    }
}

void PLScannerWindowImpl::setParams(const ProductParams& params)
{
    OI_Q(PLScannerWindow);

    if (_params != params)
    {
        _params = params;

        updateFormular();

        _work->setParams(params);

        for (int i = 0; i < _pages->count(); i++)
        {
            auto page = _pages->widget(i);

            PageAbstract* pa = qobject_cast<PageAbstract*> (page);

            if (pa)
            {
                pa->setParams(params);
            }
        }
    }
}

void PLScannerWindowImpl::setTitleStatus(int status)
{
    if (_interfaceError > 0)
    {
        status = _interfaceError;
    }

    if(status == 0)
    {
        _titleStatus->setText(PLScannerWindow::tr("准备就绪"));
        _titleStatus->setStyleSheet("background-color: rgb(255, 255, 0);color:black");
    }
    else if(InspectionPass(status))
    {
        _titleStatus->setText(InspectionString(status));
        _titleStatus->setStyleSheet("background-color: rgb(0, 255, 0);color:black");
    }
    else if(status == WorkResult::RC_Warning)
    {
        _titleStatus->setText(InspectionString(status));
        _titleStatus->setStyleSheet("background-color: rgb(255, 255, 0);color:black");
    }
    else
    {
        _titleStatus->setText(InspectionString(status));
        _titleStatus->setStyleSheet("background-color: rgb(255, 0, 0);color:black");
    }
}

void PLScannerWindowImpl::onUserUpdate()
{
    if (UserManage::instance()->current().isEmpty())
    {
        _userLabel->setText(PLScannerWindow::tr("未登录"));
        return;
    }

    QString text;

    if (UserManage::instance()->permission() == PT_Administrator)
    {
        text.append(PLScannerWindow::tr("管理员:"));
        text.append(UserManage::instance()->current());
    }
    else if ((UserManage::instance()->permission() & PT_Technologist) == PT_Technologist)
    {
        text.append(PLScannerWindow::tr("工艺员:"));
        text.append(UserManage::instance()->current());
    }
    else
    {
        if (UserManage::instance()->team() == 0)
        {
            text.append(PLScannerWindow::tr("A班:"));
        }
        else if (UserManage::instance()->team() == 1)
        {
            text.append(PLScannerWindow::tr("B班:"));
        }
        else if (UserManage::instance()->team() == 2)
        {
            text.append(PLScannerWindow::tr("C班:"));
        }
        text.append(UserManage::instance()->current());
    }

    _userLabel->setText(text);

    
    for (int i = 0; i < _pages->count(); i++)
    {
        auto page = _pages->widget(i);

        PageAbstract* pa = qobject_cast<PageAbstract*> (page);

        if (pa)
        {
            pa->updatePermission();
        }
    }
}

PLScannerWindow::PLScannerWindow(QWidget *parent) : Oi::RibbonMainWindow(parent)
{
    OI_I(PLScannerWindow)->init();
    QTimer::singleShot(1000, this, SLOT(deleteCsv()));

}

PLScannerWindow::~PLScannerWindow()
{
    OI_E(PLScannerWindow)->exit();
}

void PLScannerWindow::closeEvent(QCloseEvent* evt)
{
    OI_F(PLScannerWindow);

    if (!d->_future.isFinished())
    {
        evt->setAccepted(false);
    }
    else
    {
        if (!PLScanner::instance()->super && !(UserManage::instance()->permission() & PT_Exit))
        {
            OiAlerter() << tr("权限不足，请打开该用户退出权限");
            evt->setAccepted(false);
            return;
        }

        if(QMessageBox::Yes == QMessageBox::information(this, tr("提示"), tr("确定关闭程序？"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes))
        {
            onClose();
        }
        else
        {
            evt->setAccepted(false);
        }
    }
}

void PLScannerWindow::appendHistory(const QString& text)
{
    if (OI_IMPL()->_progOutput) OI_IMPL()->_progOutput->append(text.toHtmlEscaped());
}

void PLScannerWindow::appendWarning(const QString& text)
{
    if (OI_IMPL()->_progOutput) OI_IMPL()->_progOutput->append("<span style=\"color:orange\">" + text.toHtmlEscaped() + "</span>");
}

void PLScannerWindow::appendMessage(const QString& text)
{
    if (OI_IMPL()->_progOutput) OI_IMPL()->_progOutput->append(text.toHtmlEscaped());
}

void PLScannerWindow::appendAlerter(const QString& text)
{
    Oi::OfficePopupWindow::showPopup(this, QIcon(":/resources/images/Info.png"), tr(""), text);
}

void PLScannerWindow::appendSubject(const QString& text)
{
    if (OI_IMPL()->_progOutput) OI_IMPL()->_progOutput->append(text.toHtmlEscaped(), MessageOutput::alarm);
}

void PLScannerWindow::clearAlarm(const QString& text)
{
    if (OI_IMPL()->_progOutput) OI_IMPL()->_progOutput->clear(text);
}

void PLScannerWindow::setProgressValue(const int value)
{
    OI_F(PLScannerWindow);
    if (value < 100)
    {
        if (d->_progress->isHidden())
        {
            d->_progress->show();
        }

        d->_progress->setValue(value);
    }
    else
    {
        d->_progress->setValue(100);
        if (!d->_progress->isHidden())
        {
            d->_progress->hide();
        }
    }
}

void PLScannerWindow::showStatusMsg(const QString& text)
{
    OI_IMPL()->_statusLabel->setText(text);
}


void PLScannerWindow::onOutputVisibilityChanged(bool enable)
{
    if (enable)
    {
        OI_IMPL()->relocateOutput();
    }
}

void PLScannerWindow::onButtonGroupTriggered(int id)
{
    OI_F(PLScannerWindow);

    int index = id;

    int current = d->_pages->currentIndex();

    if (index != current)
    {
        if (index == 2)
        {
            if (d->_pageFlag == PMP_ThicknessMeasure)
            {
                if (d->_work->isRunning() == 1)
                {
                    if (QMessageBox::Yes == QMessageBox::information(this, tr("切换运行模式确认"), tr("是否停止行程测量模式，并切换至定点测量模式？"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes))
                    {
                        d->_pageFlag = PMP_FixedMeasure;
                        d->_work->stop();
                    }
                }
                else
                {
                    d->_pageFlag = PMP_FixedMeasure;
                }
            }
        }

        else if (index < 2)
        {
            if (d->_pageFlag == PMP_FixedMeasure)
            {
                if (d->_work->isRunning() == 2)
                {
                    if (QMessageBox::Yes == QMessageBox::information(this, tr("切换运行模式确认"), tr("是否停止定点测量模式，并切换至行程测量模式？"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes))
                    {
                        d->_pageFlag = PMP_ThicknessMeasure;
                        d->_work->stop();
                    }
                }
                else
                {
                    d->_pageFlag = PMP_ThicknessMeasure;
                }
            }
        }

        if (index >= 0)
        {
            d->_pages->setCurrentIndex(index);
        }

        d->updateTitle();
    }
}

void PLScannerWindow::deleteCsv()
{
    auto settings = Core::OiSettings();
    QString rootDir = Core::OiGetPermanentDir(RootDir).replace("\\", "/");
    QString dataDir = settings->value("Dir/DataDir", rootDir + "/data").toString();
    QDir dir;
    QStringList filters;
    QFileInfoList fileList;
    filters << QString("*.csv");
    dir.setPath(dataDir);
    dir.setNameFilters(filters);
    QDirIterator iter(dir, QDirIterator::Subdirectories);
    while (iter.hasNext())
    {
        iter.next();
        QFileInfo info = iter.fileInfo();
        if (info.isFile())
        {
            fileList.append(info);
        }
    }
 
    QDateTime currentTime = QDateTime::currentDateTime();//系统当前时间
    currentTime = currentTime.addDays(-7);
    QFileInfo fileInfo;
    bool bIsFind = false;
    foreach(fileInfo, fileList)
    {
        QDateTime createTime = fileInfo.lastModified();
        QString str = createTime.toString("yyyy-MM-dd hh:mm:ss");
        QString str1 = currentTime.toString("yyyy-MM-dd hh:mm:ss");
        uint stime = currentTime.toTime_t();

        uint etime = createTime.toTime_t();
        int tRet = stime - etime;
        if (tRet > 0)
        {
            fileInfo.dir().remove(fileInfo.fileName());
        }
    }
    QTimer::singleShot(24*60*60*1000, this, SLOT(deleteCsv()));
}

void PLScannerWindow::onUser()
{
    OI_F(PLScannerWindow);
    UserDlg dlg;

    dlg.resize(900, 600);
    dlg.exec();

    d->onUserUpdate();
}

void PLScannerWindow::onZero()
{
    OI_F(PLScannerWindow);

    if (!PLScanner::instance()->super && !(UserManage::instance()->permission() & PT_ZeroCalib))
    {
        OiAlerter() << tr("权限不足，请打开该用户标定权限");
        return;
    }

    if (d->_work->isRunning() > 0)
    {
        OiAlerter() << tr("请先停止设备运行");
        return;
    }

    if (SensorAcquire::OiAcquire()->isWorking())
    {
        OiAlerter() << tr("请先停止数据采集");
        return;
    }

    if (QMessageBox::Yes == QMessageBox::information(this, tr("确认"), tr("是否确认进行零点校准"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No))
    {
        Motor::instance()->home();

        showStatusMsg(tr("正在等待轴回零"));

        int timerCounter = 0;

        while (!Motor::instance()->isReady())
        {
            QEventLoop loop;
            QTimer::singleShot(100, &loop, SLOT(quit()));
            loop.exec();

            if (timerCounter > 300)
            {
                showStatusMsg(tr("等待轴回零超时"));
                return;
            }

            timerCounter++;

        }

        showStatusMsg(tr("回零完成"));
    }
}

void PLScannerWindow::onClose()
{
    OI_F(PLScannerWindow);

    Motor::instance()->locateMode();
    Motor::instance()->locatedRun(0.0);

    Motor::instance()->setResult(10000);

    d->_work->stop();

    PLScannerCore::StatusReaderSystem::instance()->clear();
    PLScannerCore::ParamsReaderSystem::instance()->clear();
    PLScannerCore::OutputWriterSystem::instance()->clear();

    PLScannerCore::Motor::instance()->exit();
}

void PLScannerWindow::onReady()
{
    OI_F(PLScannerWindow);
    
    d->_progress->hide();

    d->_acquire = SensorAcquire::OiAcquire();

    d->_acquire->init();

    showStatusMsg(PLScannerWindow::tr("准备就绪"));

// 
    if(!Database::instance()->open())
    {
        PLScannerError::instance()->reportError(PLScannerError::ERR_DATEBASE_OPEN_FAILED);
    }

//    connect(Database::instance(), &Database::dataChanged, this, &PLScannerWindow::onDatabaseUpdate, Qt::BlockingQueuedConnection);

    if (!PLScanner::instance()->simulation)
    {
        PLScannerCore::Motor::instance()->init();
    }

    ProductParams::setNext("");
    updateParams();

    auto user = Core::OiSettings()->value("CurrentUser").toString();

    auto ret = UserManage::instance()->setCurrent(user, "");
    if (ret != 0)
    {
        while (!UserDlg::callLogin(this))
        {
        }
    }

    d->onUserUpdate();
    setWindowState(Qt::WindowMaximized);
    if(PLScanner::instance()->running)
    {
        onStart();
    }
}

void PLScannerWindow::onStart()
{
    OI_F(PLScannerWindow);

    if(d->_work->isRunning() > 0)
    {
        d->_work->stop();
    }
    else
    {
        if (!ProductParams::next().isEmpty())
        {
            ProductParams::setCurrent(ProductParams::next());
            ProductParams::setNext("");
        }

        if (!updateParams())
        {
            OiAlerter() << "模板更新失败！";
            return;
        }
        if (d->_pageFlag == PMP_ThicknessMeasure)
        {
            d->_work->start(0);
        }
    }
}

void PLScannerWindow::onOpen()
{
    OI_F(PLScannerWindow);
    auto fileName = QFileDialog::getOpenFileName(this, tr("选择文件"), PLScanner::instance()->recordDir, tr("Raw File(*.csv);;Result File(*.PLSD)"));

    if (QFileInfo(fileName).exists())
    {
        if (QFileInfo(fileName).suffix().toLower() == "csv")
        {
            d->_work->open(fileName);
        }
        else if (QFileInfo(fileName).suffix().toLower() == "plsd")
        {

        }
    }
}

void PLScannerWindow::onProduct()
{
    OI_F(PLScannerWindow);

    ProductDlg dlg(d->_pageFlag, this);
    auto dg = QApplication::desktop()->availableGeometry();
    dlg.setGeometry(100, 50, dg.width() - 200, dg.height() - 100);
    dlg.exec();

    if (!ProductParams::next().isEmpty())
    {
        if (d->_work->isRunning())
        {
            OiAlerter() << tr("当前规格正在执行，无法立即切换新规格，新规格将在手动停止后得到应用");

            d->updateFormular();
        }
        else
        {
            ProductParams::setCurrent(ProductParams::next());
            ProductParams::setNext("");
            updateParams();
        }
    }
}

void PLScannerWindow::onImport()
{
    OI_F(PLScannerWindow);
    auto fileName = QFileDialog::getOpenFileName(this, tr("选择文件"), PLScanner::instance()->recordDir, tr("JS对象(*.json)"));

    if (QFileInfo(fileName).exists())
    {
        auto ret = ProductParams::loadFromJson(fileName);

        if (ret == 0)
        {
            OiAlerter() << tr("导入失败");
        }
        else
        {
            OiAlerter() << tr("成功导入%1条配方").arg(ret);
        }
    }
}

void PLScannerWindow::onSave()
{
    OI_F(PLScannerWindow);

    QString dir = QString("%1/PLScanner-Outputs-%2.PLSD")
        .arg(PLScanner::instance()->recordDir)
        .arg(QDateTime::currentDateTime().toString("yyyyMMdd-HHmmss"));

    d->_work->save(dir);

    showStatusMsg(PLScannerWindow::tr("已保存数据至")+dir);
}

bool PLScannerWindow::updateParams()
{
    OI_F(PLScannerWindow);
    int ret = 0;
    auto param = ProductParams::params(ret);
    if (ret == 0)
    {
        d->setParams(param);
        d->_interfaceError = 0;
        d->setTitleStatus(0);
        return true;
    }
    else
    {
        d->updateFormular();
        d->setTitleStatus(WorkResult::RC_Formualr_Disable);
        d->_interfaceError = WorkResult::RC_Formualr_Disable;
        return false;
    }
}

void PLScannerWindow::onParamsChanged()
{
    OI_F(PLScannerWindow);

    auto nextName = ProductParams::next();

    if (!nextName.isEmpty())
    {
        if (d->_work->isRunning())
        {
            d->updateFormular();

            if (PLScanner::instance()->paramMode == 2)
            {
                QTimer::singleShot(1000 * PLScanner::instance()->switchDelayStopTime, this, SLOT(stopWork()));
            }
            
        }
        else
        {
            ProductParams::setCurrent(nextName);
            ProductParams::setNext("");

            if (updateParams())
            {
                if (PLScanner::instance()->paramMode == 2)
                {
                    QTimer::singleShot(1000 * PLScanner::instance()->switchDelayStartTime, this, SLOT(startWork()));
                }
            }
        }
    }
}

void PLScannerWindow::startWork()
{
    OI_F(PLScannerWindow);

    if (d->_work->isRunning() == 0)
    {
        if (!ProductParams::next().isEmpty())
        {
            ProductParams::setCurrent(ProductParams::next());
            ProductParams::setNext("");

            if (!updateParams())
            {
                return;
            }
        }

        OiWarning() << "Start Work:" << d->_params.specName;

        if (d->_pageFlag == PMP_FixedMeasure)
        {
            d->_work->start(1);
        }
        else if (d->_pageFlag == PMP_ThicknessMeasure)
        {
            d->_work->start(0);
        }
    }
}

void PLScannerWindow::stopWork()
{
    OI_F(PLScannerWindow);

    if (d->_work->isRunning() > 0)
    {
        d->_work->stop();
    }

    OiWarning() << "Stop Work";
   
    if (PLScanner::instance()->paramMode == 2)
    {
        QTimer::singleShot(1000 * PLScanner::instance()->switchDelayStartTime, this, SLOT(startWork()));
    }
}

void PLScannerWindow::onCalibration()
{
    OI_F(PLScannerWindow);
    if (!PLScanner::instance()->super && !(UserManage::instance()->permission() & PT_Calib))
    {
        OiAlerter() << tr("权限不足，请打开该用户标定权限");
        return;
    }

    if (d->_work->isRunning())
    {
        OiAlerter() << tr("请先停止设备运行");
        return;
    }

    if (SensorAcquire::OiAcquire()->isWorking())
    {
        OiAlerter() << tr("请先停止数据采集");
        return;
    }

    if (QMessageBox::Yes != QMessageBox::information(this, tr("提示"), tr("请确认L型标定块是否已取下？"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No))
    {
        return;
    }

    CalibDlg dlg;

    dlg.resize(400, 300);

    dlg.exec();
}

void PLScannerWindow::onCalibration2()
{
    OI_F(PLScannerWindow);
    if (!PLScanner::instance()->super && !(UserManage::instance()->permission() & PT_Calib))
    {
        OiAlerter() << tr("权限不足，请打开该用户标定权限");
        return;
    }

    if (d->_work->isRunning())
    {
        OiAlerter() << tr("请先停止设备运行");
        return;
    }

    if (SensorAcquire::OiAcquire()->isWorking())
    {
        OiAlerter() << tr("请先停止数据采集");
        return;
    }

    if (QMessageBox::Yes != QMessageBox::information(this, tr("提示"), tr("请确认L型标定块是否已安装？"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No))
    {
        return;
    }

    WideCalibDlg dlg;

    dlg.resize(1200, 800);

    dlg.exec();
}

void PLScannerWindow::onVerification()
{
    if (!PLScanner::instance()->super && !(UserManage::instance()->permission() & PT_Verification))
    {
        OiAlerter() << tr("权限不足，请打开该用户验证权限");
        return;
    }
}

void PLScannerWindow::onSettings()
{
    OI_F(PLScannerWindow);

    SettingsDlg dlg(this);

    dlg.resize(800, 600);
    if(dlg.exec() == QDialog::Accepted)
    {
        dlg.saveParams();
    }
}

void PLScannerWindow::onSuper(bool enabled)
{
    QString text;

    auto action = qobject_cast<QAction*>( sender() );

    if(enabled)
    {
            QByteArray password = QByteArray::fromHex("712c9491074e16a77924a5c673c53c64");
            bool ok = false;
            QString text = Ctrl::TouchInputDialog::getText(this, tr("验证密码"), tr("请输入密码:"), Ctrl::TouchInputDialog::Secret, 1, Core::Value(QString("")), &ok, Qt::WindowCloseButtonHint | Qt::Dialog).value<QString>();

            if(!ok)
            {
                action->setChecked(false);
                return;
            }

            if(QCryptographicHash::hash(( Core::OiBaseCreatorName() + text ).toLatin1(), QCryptographicHash::Md5) != password)
            {
                OiAlerter() << tr("密码错误!");
                action->setChecked(false);
                return;
            }

            OiAlerter() << tr("开启超级管理员成功!");
    }

    PLScanner::instance()->super = enabled;
}

void PLScannerWindow::onResultUpdate()
{
    OI_F(PLScannerWindow);

    double elW = 0.0;

    if (PLScanner::instance()->elWidthOption == 1)
    {
        elW = Leader_Udp::instance()->value();
    }
    else if (PLScanner::instance()->elWidthOption == 2)
    {
        OPCTask::instance()->readELWidth(elW);
    }

    if (d->_pageFlag == PMP_FixedMeasure)
    {
        auto result = d->_work->value();

        int ret = d->_page2->setValue(result, elW);

        d->setTitleStatus(ret);
    }

    else if (d->_pageFlag == PMP_ThicknessMeasure)
    {
        auto result = d->_work->result();

        result.data["tolWidth2"] = elW;

       // d->setTitleStatus(result.result);

        for (int i = 0; i < d->_pages->count(); i++)
        {
            auto page = d->_pages->widget(i);

            PageAbstract* pa = qobject_cast<PageAbstract*> (page);

            if (pa)
            {
                int ret = pa->setResult(result);

                if (page == d->_page0)
                {
                    result.result = ret;

                    d->setTitleStatus(ret);
                }
            }
        }
    }
}

void PLScannerWindow::onEnterTask()
{
    OI_F(PLScannerWindow);

    d->_startAction->setIcon(QIcon(":/resources/images/ExecuteAllStop.png"));
    d->_startAction->setToolTip("停止运行");
    d->_pStartTitleBtn->setText("(F7) " + tr("停止"));

    showStatusMsg(PLScannerWindow::tr("已开启任务"));

    auto pages = findChildren<PageAbstract*>();

    for (auto& page : pages)
    {
        page->run(true);
    }
}

void PLScannerWindow::onLeaveTask()
{
    OI_F(PLScannerWindow);

    d->_startAction->setIcon(QIcon(":/resources/images/ExecuteAll.png"));
    d->_startAction->setToolTip("开始运行");
    d->_pStartTitleBtn->setText("(F7) " + tr("启动"));


    showStatusMsg(PLScannerWindow::tr("已停止任务"));
}

void PLScannerWindow::onLanguage()
{
    QAction* language = qobject_cast<QAction*>(sender());

    if (language->data().toInt() == -1)
    {
        Core::OiSettings()->object()->setValue("locale", QVariant());
    }
    else
    {
        Core::OiSettings()->object()->setValue("locale", language->text());
    }

    Oi::OfficePopupWindow::showPopup(this, QIcon(":/resources/images/Info.png"), tr("提示信息"), tr("请重启软件使语言设置生效。"));
}

void PLScannerWindow::onHelp()
{
//     auto aa = DownloadSaveFiles("https://p9.itc.cn/mpbp/pro/20210426/d3e9bbb1f7b944a39763c8afdb42b17f.jpeg", "C:/Users/John/Desktop/新建文件夹/1.jpeg");
//     int bb = 0;
    QDesktopServices::openUrl(QUrl::fromLocalFile(PLScanner::instance()->rootDir + "/doc/" + PLScanner::instance()->manual));
}

void PLScannerWindow::onAbout()
{
    QMessageBox about(QMessageBox::Information, tr("关于%1").arg(PLScanner::instance()->softName),
        tr("<h2>%1 %2</h2>"
        "<p>Copyright &copy; %3 %1 %4"
        "<p>%2 是一款专门用于轮胎半制品厚度测量的软件"
        "<p>当前版本 %5"
        "<p>编译版本 %6")
        .arg(PLScanner::instance()->company)
        .arg(PLScanner::instance()->softName)
        .arg(PLScanner::instance()->companyLocal)
        .arg("Co., Ltd.")
        .arg(PLScanner::instance()->softVersion)
        .arg(__DATE__)
    );

    about.setWindowIcon(QIcon(":/"+PLScanner::instance()->resourceName+ "/" + PLScanner::instance()->icon));
    about.setIconPixmap(QPixmap(":/"+PLScanner::instance()->resourceName+ "/" +PLScanner::instance()->companyLogo));
    about.exec();
}

} }
